package com.tanhua.server.service;

import com.alibaba.fastjson.JSON;
import com.tanhua.commons.templates.AipFaceTemplate;
import com.tanhua.commons.templates.OssTemplate;
import com.tanhua.commons.templates.SmsTemplate;
import com.tanhua.domain.db.User;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.vo.ErrorResult;
import com.tanhua.domain.vo.UserInfoVo;
import com.tanhua.dubbo.api.UserApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.server.interceptor.UserHolder;
import com.tanhua.server.utils.JwtUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;


import java.io.IOException;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

/**
 * 注意：这里倒入Spring的包：org.springframework.stereotype.Service
 * 因为不是dubbo服务
 */
@Service
public class UserService {
    /**
     * 注入dubbo服务接口的代理对象，导入dubbo的包
     */
    @Reference
    private UserApi userApi;
    @Autowired
    private SmsTemplate smsTemplate;
    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    // 定义redis中存储的验证码的key的前缀
    private final String SMS_KEY = "SMS_KEY_";
    //获取token
    @Value("${tanhua.secret}")
    private String secret;
    @Reference
    private UserInfoApi userInfoApi;
    @Autowired
    private AipFaceTemplate aipFaceTemplate;
    @Autowired
    private OssTemplate ossTemplate;
    //定义redis中存储token的key的前缀
    private final String TOKEN_KEY = "TOKEN_KEY_";

    /**
     * 测试1、根据手机号码查询
     * @param mobile
     * @return
     */
    public ResponseEntity<Object> findByMobile(String mobile){
        User user = userApi.findByMobile(mobile);
        //通过ResponseEntity往响应体中写数据
        return ResponseEntity.ok(user);
    }

    /**
     * 测试2、保存手机号码
     * @param user
     * @return
     */
    public ResponseEntity<Object> save(User user){
        Long userId = userApi.save(user);
        return ResponseEntity.ok(userId);
    }

    /**
     * 接口名称：登录第一步---手机号登录
     * 需求描述：给传入的手机号码发送短信验证码
     */
    public ResponseEntity<Object> sendSms(String phone){
        //1. 生成短信验证码
        String code = (int)((Math.random() * 9 + 1) * 100000) + "";
        code = "123456";

        //2. 调用工具发送短信
//        smsTemplate.sendSms(phone,code);

        //3. 验证码存储到redis中，key是: SMS_KEY_ + 手机号; 有效时间5分钟
        redisTemplate.opsForValue().set(SMS_KEY + phone,code, Duration.ofMinutes(5));
        return ResponseEntity.ok(null);
    }

    /**
     * 接口名称：登录第二步---验证码校验
     * 需求描述：根据用户输入的验证码进行校验
     */
    public ResponseEntity<Object> loginVerification(String phone,String verificationCode){
        //1. 从redis中获取验证码并校验验证码
        String redisCode = redisTemplate.opsForValue().get(SMS_KEY + phone);
        if (redisCode == null || !verificationCode.equals(redisCode)){
            //返回错误
            return ResponseEntity.status(500).body(ErrorResult.error());
        }

        //2. 校验完毕，从redis中删除验证码
        redisTemplate.delete(SMS_KEY+phone);

        //3.根据手机号码查询用户
        User user = userApi.findByMobile(phone);
        boolean isNew = false;
        //3.1 判断手机号码如果不存在就自动注册
        if (user == null){
            user = new User();
            user.setMobile(phone);
            user.setPassword(DigestUtils.md5Hex("123456"));
            //添加用户
            Long id = userApi.save(user);
            user.setId(id);
            //设置为新用户
            isNew = true;
        }

        //生成token，存储token到redis中
        String token = JwtUtils.createToken(user.getId(), phone, secret);
        //往token中存储的应该是整个用户对象数据，所以这里需要把对象转换为json字符串存储
        String userJsonString = JSON.toJSONString(user);
        //生成的token作为key，用户数据作为value，存储到redis中，并设置过期时间
        redisTemplate.opsForValue().set(TOKEN_KEY+token,userJsonString,Duration.ofHours(4));

        //4. 构造返回结果
        Map<String,Object> resultMap = new HashMap<>();
        resultMap.put("token",token);
        resultMap.put("isNew",isNew);
        return ResponseEntity.ok(resultMap);
    }

    /**
     * 接口名称：新用户---1填写资料
     */
    public ResponseEntity<Object> saveUserInfo(UserInfo userInfo, String token) {
        //根据token获取用户
        User user = this.findUserByToken(token);
        if (user == null){
            //认证失败
            return ResponseEntity.status(500).body(ErrorResult.error());
        }
        //设置用户详情id
        userInfo.setId(user.getId());
        //保存
        userInfoApi.save(userInfo);//下一章实现
        return ResponseEntity.ok(null);
    }

    /**
     * 根据token查找用户
     */
    public User findUserByToken(String token){
        //根据token，获取用户信息（json字符串）
        String userJsonString = redisTemplate.opsForValue().get(TOKEN_KEY + token);
        if (userJsonString == null){
            return null;
        }
        //把json字符串转换为对象
        User user = JSON.parseObject(userJsonString,User.class);
        //更新token有效事件
        redisTemplate.opsForValue().set(TOKEN_KEY +token,userJsonString,Duration.ofHours(4));
        return user;
    }

    /**
     * 接口名称：新用户---2选取头像
     */
    public ResponseEntity<Object> updateUserHead(MultipartFile headPhoto,String token) throws IOException {
        //1、根据token获取用户
        User user = findUserByToken(token);

        //2、图片人脸检测
        boolean detect = aipFaceTemplate.detect(headPhoto.getBytes());
        if (!detect){
            //人脸识别校验失败
            return ResponseEntity.status(500).body(ErrorResult.faceError());
        }

        //3、将拍摄的人来拿上传到阿里云oss
        String url = ossTemplate.upload(headPhoto.getOriginalFilename(), headPhoto.getInputStream());

        //4、修改用户详情（头像信息）
        UserInfo userInfo = new UserInfo();
        user.setId(user.getId());
        userInfo.setAvatar(url);
        userInfoApi.update(userInfo);
        return ResponseEntity.ok(null);
    }

    /**
     * 接口名称：用户资料 - 读取
     * @return
     */
    public ResponseEntity<Object> findUserInfoById(){
        //根据token获取用户
//        User user = findUserByToken(token);
        User user = UserHolder.get();

        //根据用户id查询用户详情：UserInfo
        UserInfo userInfo = userInfoApi.findById(user.getId());

        //返回的数据通过vo封装
        UserInfoVo userInfoVo = new UserInfoVo();
        BeanUtils.copyProperties(userInfo,userInfoVo);
        //处理年龄类型不一致
        if (userInfo.getAge() != null){
            userInfoVo.setAge(userInfo.getAge().toString());
        }
        return ResponseEntity.ok(userInfoVo);
    }

    /**
     * 接口名称：用户资料 - 保存
     */
    public ResponseEntity<Object> updateUserInfo(UserInfo userInfo){
        //根据token获取用户
//        User user = findUserByToken(token);
        User user = UserHolder.get();
        //更新用户
        userInfo.setId(user.getId());
        userInfoApi.update(userInfo);
        return ResponseEntity.ok(null);
    }
}
